﻿using System;
using System.Collections.Generic;
using System.Text;

namespace TLang.Ast
{
    using Values;

    public class Declare : Node
    {
        public Scope propertyForm;


        public Declare(Scope propertyForm, String file, int start, int end, int line, int col) : base(file, start, end, line, col)
        {
            this.propertyForm = propertyForm;
        }


        public override Value Interp(Scope s)
        {
            //        mergeProperties(propsNode, s);
            return Value.VOID;
        }

        public override Value Typecheck(Scope s)
        {
            return null;
        }


        public static void mergeDefault(Scope properties, Scope s)
        {
            foreach (String key in properties.Keys)
            {
                Object defaultValue = properties.LookupPropertyLocal(key, "default");
                if (defaultValue == null)
                {
                    continue;
                }
                else if (defaultValue is Value)
                {
                    Value existing = s.Lookup(key);
                    if (existing == null)
                    {
                        s.PutValue(key, (Value)defaultValue);
                    }
                }
                else
                {
                    Util.Abort("default value is not a value, shouldn't happen");
                }
            }
        }


        public static void mergeType(Scope properties, Scope s)
        {
            foreach (String key in properties.Keys)
            {
                if (key.Equals(Constants.RETURN_ARROW))
                {
                    continue;
                }
                Object type = properties.LookupPropertyLocal(key, "type");
                if (type == null)
                {
                    continue;
                }
                else if (type is Value)
                {
                    Value existing = s.Lookup(key);
                    if (existing == null)
                    {
                        s.PutValue(key, (Value)type);
                    }
                }
                else
                {
                    Util.Abort("illegal type, shouldn't happen" + type);
                }
            }
        }


        public static Scope evalProperties(Scope unevaled, Scope s)
        {
            Scope evaled = new Scope();

            foreach (String field in unevaled.Keys)
            {
                Map<String, Object> props = unevaled.LookupAllProps(field);
                foreach (var e in props)
                {
                    Object v = e.Value;
                    if (v is Node)
                    {
                        Value vValue = ((Node)v).Interp(s);
                        evaled.Put(field, e.Key, vValue);
                    }
                    else
                    {
                        Util.Abort("property is not a node, parser bug: " + v);
                    }
                }
            }
            return evaled;
        }


        public static Scope typecheckProperties(Scope unevaled, Scope s)
        {
            Scope evaled = new Scope();

            foreach (String field in unevaled.Keys)
            {
                if (field.Equals(Constants.RETURN_ARROW))
                {
                    evaled.PutProperties(field, unevaled.LookupAllProps(field));
                }
                else
                {
                    Map<String, Object> props = unevaled.LookupAllProps(field);
                    foreach (var e in props)
                    {
                        Object v = e.Value;
                        if (v is Node)
                        {
                            Value vValue = ((Node)v).Typecheck(s);
                            evaled.Put(field, e.Key, vValue);
                        }
                        else
                        {
                            Util.Abort("property is not a node, parser bug: " + v);
                        }
                    }
                }
            }
            return evaled;
        }


        public override String ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(Constants.PAREN_BEGIN);
            sb.Append(Constants.DECLARE_KEYWORD).Append(" ");

            foreach (String field in propertyForm.Keys)
            {
                Map<String, Object> props = propertyForm.LookupAllProps(field);
                foreach (var e in props)
                {
                    sb.Append(" :" + e.Key + " " + e.Value);
                }
            }

            sb.Append(Constants.PAREN_END);
            return sb.ToString();
        }
    }
}
